

#ifndef AUX_HPP
#define AUX_HPP

#include "common.hpp"

#include <QtWi>
#include <QtWiTmpl>

extern "C" {
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
}

class Proc
{
private:
	int read_buf_max; 
	char *path;
	int fd;

public:
	class ProcOperationFailed { };

	Proc() : read_buf_max(256) { }
	
	Proc(const char *p) : read_buf_max(256), path(const_cast<char *>(p))
	{
		if((fd = open(path, O_RDWR)) < 0)
			throw ProcOperationFailed();
	}

	~Proc()
	{
		//close(fd);
		//fd = -1;
	}

	void send(const char *str) const;

	std::string receive() const;

	bool isSet() const
	{
		std::string val = receive();
		return (val.substr(0, 1) == "1");
	}

	void set(bool val)
	{
		send(val ? "1" : "0");
	}

};

// Wrapper class for C-style timer function
class PrimitiveTimer
{
	
public:
	int timer(struct timeval *elapsed) const
	{
		static struct timeval start;
		struct timeval end;

		if(!elapsed) {
			if(gettimeofday(&start, NULL) < 0)
				return -1;
		} else {
			if(!start.tv_sec || gettimeofday(&end, NULL) < 0)
				return -1;
			elapsed->tv_sec = end.tv_sec - start.tv_sec;		
			elapsed->tv_usec = end.tv_usec - start.tv_usec;
		}
		
		return 0;
	}
};

// Wrapper class for C-style rando number generator using /dev/random
class PrimitiveRandomizer
{

 public:
	
	static uint32_t random_long(int not_signed)
	{
		static const char *random_file = "/dev/urandom";
		static int fd;
		uint32_t random;
	
		if(!fd)
			fd = open(random_file, O_RDONLY);

		size_t have_read = 0, to_read = sizeof(long int);

		for(; to_read > 0; to_read -= have_read)
			have_read = read(fd, ((char*)&random) + have_read, to_read);

		return not_signed ? random & ~(0x1 << (sizeof(uint32_t) * 8 - 1)) : random;
	}
};


class Timing : public ILabeledTextBox, public ITimerHandler
{
private:
	unsigned int current;
	unsigned int interval;
	bool running;
	ValueLogger logger;
	
public:
	Timing(Ifactory &f, IWidget &parent, int x, int y, int w, int h, int itv) :
		ILabeledTextBox(parent, f, "Time", x, y, w, h), interval(itv),
		logger("time")
	{
		current = 0;
		running = false;
		f.getApp().registerTimer(this, textbox(), interval * 1000);
	}

	virtual void timeout()
	{
		if(!running) return;
		current += interval;
		std::string cur = to_string<unsigned>(current) + " s";
		textbox()->setText(const_cast<char*>(cur.c_str()));
		logger.out() << current << std::endl;
	}

	void run()
	{
		running = true;
	}

	void reset()
	{
		current = 0;
	}
	
	void stop()
	{
		running = false;
	}
};

#endif /* AUX_HPP */
